package pta_11_8;

import java.util.Scanner;

//这个题就能很好的说明抽象类的意义  


abstract class Shape {
	/*
	 * 首先  将所有平面几何图形抽象成一个abstract class Shape 
	 * 所有平面几何图形都有计算面积和周长的需求  
	 * 因此在这个Shape类里面声明了两个求面积和周长的方法  
	 * 这两个方法只是在这里进行了声明，并没有具体的实现，
	 * 这是因为当前的Shape不够具体，我们不知道该怎么求一个不具体的图形的面积或者周长 
	 * 因此在抽象类里面的方法是没办法给出具体的实现的  
	 */
	public abstract double getArea();
	public abstract double getPerimeter(); 
}
class Circle extends Shape{
	//通过继承Shape方法实现Circle类
	/*
	 * 这时候 这个图形才变得具体起来了  
	 * 一个圆是有办法求面积和周长的  
	 *  因此在这个圆的类里面 对getArea()  
	 *  和getPerimeter()方法进行实现
	 */
	private double r; //半径
	@Override
	public double getArea() {
		return Math.PI * r * r;
	}
	@Override
	public double getPerimeter() {
		return Math.PI * 2 * r;
	}
	public Circle(double r) {
		this.r = r;
	}
}
class Rectangle extends Shape{
	//通过继承Shape方法实现Rectangle类

	double l , w; //长和宽
	public Rectangle(double l , double w) {
		this.l = l;
		this.w = w;
	}
	@Override
	public double getArea() {
		return l * w;
	}
	@Override
	public double getPerimeter() {
		return 2 * (w + l);
	}
}
public class Area{
	public static void main(String[] args) {
		double area = 0;
		Scanner s = new Scanner(System.in);
		
		
		/*
		 * 在这里  就能体现出来使用抽象类的一个好处
		 * 这里我们需要将圆和矩形两种不同的东西放在同一个数组里面
		 * 但是我们知道数组里面的元素类型必须是相同的
		 * 这种情况下  由于矩形和圆 都属于Shape类，
		 * 因此  我们可以使用一个Shape类型的数组，来在一个数组里存储圆和矩形
		 * 如下*/
		Shape[] shapes = {
				new Circle(s.nextDouble()),
				new Circle(s.nextDouble()),
				new Rectangle(s.nextDouble(),s.nextDouble()),
				new Rectangle(s.nextDouble(), s.nextDouble())
				};
		/* 如果不使用这个抽象类 这里就没法把两种图形放在同一个数组里了
		 * 当然你可能觉得就算不使用抽象类  我用一个普通的Shape类也可以实现这样的作用
		 * 没错，是可以   但是你用一个普通的Shape类  你要在这个Shape类里面怎么实现getArea() 
		 * 和getPerimeter()这两个个方法？因为Shape类比较抽象，我们没法也不需要实现具体的方法
		 * 那么你可能就要在Shape类里面这么写  public double getArea(){ return 0; }
		 * 首先 这样写显然不如你写一个public abstract double getArea();来的优雅
		 * 而且这样还会带来问题 假如在你利用继承Shape类去实现Circle类的时候
		 * 不小心忘记了重写getArea()类  那么你的Circle类就会通过父类的getArea()方法
		 * 得到一个错误的面积(永远是0 /笑哭)
		 * 但是如果你使用抽象类  编译器(甚至是编辑器)会督促你对抽象方法进行重写，否则会有报错
		 * 这样就保证了在具体的类中一定对具体的方法进行了实现
		 * */
		s.close();
		for(Shape a : shapes) {
			/* 这是Java里非常好用的一种循环
			 * 叫做foreach循环
			 * 主要用来遍历数组
			 * 比如有一个数组 int [] array = {5 ,2 , 0};
			 * 那么  for(int a : array){
			 * 			System.out.println(a);
			 * 		}
			 * 将会打印出 5
			 * 			2
			 * 			0
			 * 这样 ，其实就等价于
			 * for(int i = 0; i<array.length i++){ 
			 * 		System.out.println(array[i]);
			 *  }
			 */

			area += a.getArea();
		}
		System.out.printf("The total area is %.4f",area);
	}
}

/*
 * 回过头来再理解一下
 * 抽象类（抽象方法）就像是一种规范
 * 规定了这一类东西应该有些什么样的功能
 * 然后在具体实现的时候  把这些功能实现出来
 * */
